package com.sz.biz.trade.ord.service.impl;

import com.github.tobato.fastdfs.domain.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.google.common.collect.Lists;
import com.sz.biz.common.constants.SystemConstants;
import com.sz.biz.common.utils.FileUtil;
import com.sz.biz.common.utils.OrderMake;
import com.sz.biz.logistics.constants.OrderConstants;
import com.sz.biz.logistics.constants.ProjectConstants;
import com.sz.biz.logistics.ord.entity.OrderDetail;
import com.sz.biz.logistics.ord.enums.OrdServiceTypeEnum;
import com.sz.biz.trade.constants.TrdErrorCodes;
import com.sz.biz.common.base.entity.ExchangeRate;
import com.sz.biz.common.customer.entity.CusUser;
import com.sz.biz.common.project.entity.Project;
import com.sz.biz.common.platform.entity.PlatformCompany;
import com.sz.biz.trade.goods.entity.GoodsType;
import com.sz.biz.common.AbstractVersionEntityService;
import com.sz.biz.common.base.service.ExchangeRateService;
import com.sz.biz.common.customer.service.CustomerService;
import com.sz.biz.common.customer.service.CustomerUserService;
import com.sz.biz.common.customer.dto.CusCustomerDto;
import com.sz.biz.common.project.service.ProjectService;
import com.sz.biz.common.sup.service.SupplierService;
import com.sz.biz.common.sup.dto.SupplierDto;
import com.sz.biz.common.platform.service.PlatformCompanyService;
import com.sz.biz.trade.bill.dto.TrdBillingGenerateDto;
import com.sz.biz.trade.goods.service.GoodsService;
import com.sz.biz.trade.goods.service.GoodsTypeService;
import com.sz.biz.trade.goods.dto.GoodsInfoDto;
import com.sz.biz.logistics.constants.ErrorCodes;
import com.sz.biz.trade.ord.dto.*;
import com.sz.biz.trade.ord.entity.*;
import com.sz.biz.trade.ord.service.*;
import com.sz.common.base.cache.redis.RedisPoolManager;
import com.sz.common.base.utils.*;
import com.sz.common.core.service.PrincipalUtils;
import com.sz.common.core.system.entity.SysFile;
import com.sz.common.core.system.service.SysFileService;
import com.sz.common.core.system.utils.PDFUtils;
import com.lowagie.text.*;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfStamper;
import com.lowagie.text.pdf.PdfWriter;
import com.sz.common.base.dao.ParamData;
import com.sz.common.base.dto.CommonModel;
import com.sz.common.base.dto.QResultDto;
import com.sz.common.base.dto.QueryParams;
import com.sz.common.base.exception.ErrorCode;
import com.sz.common.base.exception.Exceptions;
import org.apache.tomcat.util.http.fileupload.ByteArrayOutputStream;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import redis.clients.jedis.Jedis;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.net.URLDecoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Function: 贸易订单服务<br>
 * Author: jifeixing <br>
 * Date: 2017-07-15 14:10:00
 */
@Service("trdOrderService")
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class TrdOrderServiceImpl extends AbstractVersionEntityService implements TrdOrderService {

    @Autowired
    private TrdOrderGoodsRelService trdOrderGoodsRelService;

    @Autowired
    private GoodsService goodsService;

    @Autowired
    private CustomerUserService customerUserService;

    @Autowired
    private CustomerService customerService;

    @Autowired
    private TrdOrderConfirmationService trdOrderConfirmationService;

    @Autowired
    private TrdOrderDeliveryService trdOrderDeliveryService;

    @Autowired
    private FastFileStorageClient storageClient;

    @Autowired
    private SysFileService sysFileService;

    @Autowired
    private GoodsTypeService goodsTypeService;

    @Autowired
    private ProjectService projectService;

    @Autowired
    private ExchangeRateService exchangeRateService;

    @Autowired
    private TrdOrderTrackingService trdOrderTrackingService;

    @Autowired
    private TrdOrderFileRelService trdOrderFileRelService;

    @Autowired
    private SupplierService supplierService;

    @Autowired
    private PlatformCompanyService platformCompanyService;

    //默认币种类型
    private static final String DEFAULT_CURRENCY_CODE = "CNY";

    @Override
    protected String getMapperNamespace() {
        return "TrdOrderMapper";
    }

    /**
     * 根据订单号查询订单确认单
     *
     * @param orderNo
     * @return
     */
    @Override
    public TrdOrderConfirmationInfoDto getConfirmationByOrder(String orderNo) {
        if (StringUtils.isEmpty(orderNo)) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_ILLEGAL);
        }
        TrdOrder trdOrders = findFullInfoByOrderNo(orderNo);
        if (!isNeedBuildPDF(trdOrders)) {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "非SUNRUN订单,不支持导出确认单");
        }

        TrdOrderConfirmationInfoDto trdOrderConfirmationInfoDto = trdOrderConfirmationService.findByOrderNo(orderNo);
        if(null == trdOrderConfirmationInfoDto){
            TrdOrderInfoDto trdOrderInfoDto = (TrdOrderInfoDto) dao.findForObject(getSqlName("firstConfirmByOrderNoSale"), orderNo);
            if(null != trdOrderInfoDto){
                trdOrderConfirmationInfoDto = new TrdOrderConfirmationInfoDto();
                BeanUtils.copyProperties(trdOrderInfoDto, trdOrderConfirmationInfoDto);
                //商品信息
                List<TrdOrderGoodsRelDto> trdOrderGoodsRels = trdOrderGoodsRelService.findByOrderNo(orderNo, 1);
                trdOrderConfirmationInfoDto.setOrderGoods(trdOrderGoodsRels);
            }
        }
        return trdOrderConfirmationInfoDto;
    }

    /**
     * 根据订单号查询收货确认单
     *
     * @param orderNo
     * @return
     */
    @Override
    public TrdOrderDeliveryInfoDto getDeliveryByOrder(String orderNo) {
        if (StringUtils.isEmpty(orderNo)) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_ILLEGAL);
        }
        return trdOrderDeliveryService.findByOrderNo(orderNo);
    }

    /**
     * 所有订单类型
     *
     * @return
     */
    @Override
    public List<CommonModel> orderType() {
        List<CommonModel> list = Lists.newArrayList();
        for (TrdOrderType trdOrderType : TrdOrderType.values()) {
            CommonModel dto = new CommonModel(trdOrderType.name(), trdOrderType.getName());
            list.add(dto);
        }
        return list;
    }

    /**
     * 所有订单状态
     *
     * @return
     */
    @Override
    public List<CommonModel> orderStatus() {
        List<CommonModel> list = Lists.newArrayList();
        for (TrdOrderStatus trdOrderStatus : TrdOrderStatus.values()) {
            CommonModel dto = new CommonModel(trdOrderStatus.name(), trdOrderStatus.getName());
            list.add(dto);
        }
        return list;
    }

    /**
     * 客户系统客户订单详情（销售订单）
     *
     * @param orderNo
     * @return
     */
    @Override
    public TrdOrderInfoCustomerDto findByOrderNoCustomerSale(String orderNo) {
        TrdOrderInfoCustomerDto trdOrderInfoDto = (TrdOrderInfoCustomerDto) dao.findForObject(getSqlName("findByOrderNoCustomerSale"), orderNo);
        return findOrderInfoCustomer(trdOrderInfoDto, orderNo);
    }

    /**
     * 客户系统供应商订单详情（采购订单）
     *
     * @param orderNo
     * @return
     */
    @Override
    public TrdOrderInfoCustomerDto findByOrderNoCustomerPurchaser(String orderNo) {
        TrdOrderInfoCustomerDto trdOrderInfoDto = (TrdOrderInfoCustomerDto) dao.findForObject(getSqlName("findByOrderNoCustomerPurchaser"), orderNo);
        return findOrderInfoCustomer(trdOrderInfoDto, orderNo);
    }

    /**
     * 客户平台订单详情
     *
     * @return
     */
    private TrdOrderInfoCustomerDto findOrderInfoCustomer(TrdOrderInfoCustomerDto trdOrderInfoDto, String orderNo) {
        if (null != trdOrderInfoDto) {
            trdOrderInfoDto.setOrderStatusCode(trdOrderInfoDto.getOrderStatus().getCode());
            trdOrderInfoDto.setOrderStatusName(trdOrderInfoDto.getOrderStatus().getName());
            List<TrdOrderGoodsRelDto> trdOrderGoodsRels = trdOrderGoodsRelService.findByOrderNo(orderNo, 1);
            trdOrderInfoDto.setOrderGoods(trdOrderGoodsRels);
            //订单确认单
            PathPDFDto filePathConfirm = trdOrderConfirmationService.findPathByOrderNo(orderNo);
            if(null != filePathConfirm){
                trdOrderInfoDto.setOrderConfirmUrl(filePathConfirm.getPath());
            }
            //订单收货单
            PathPDFDto filePathDelivery = trdOrderDeliveryService.findPathByOrderNo(orderNo);
            if(null != filePathDelivery){
                trdOrderInfoDto.setOrderDeliverUrl(filePathDelivery.getPath());
            }
        }
        return trdOrderInfoDto;
    }

    /**
     * 根据订单号获取订单信息
     *
     * @param orderNo
     * @return
     */
    @Override
    public TrdOrder findByOrderNo(String orderNo) {
        return (TrdOrder) dao.findForObject(getSqlName("findByOrderNo"), orderNo);
    }

    /**
     * 根据订单号获取订单信息（销售订单）
     *
     * @param orderNo
     * @return
     */
    @Override
    public TrdOrderInfoDto findByOrderNoSale(String orderNo) {
        TrdOrderInfoDto trdOrderInfoDto = (TrdOrderInfoDto) dao.findForObject(getSqlName("findByOrderNoSale"), orderNo);
        return findByOrderNo(trdOrderInfoDto, orderNo);
    }

    /**
     * 根据订单号获取订单信息（采购订单）
     *
     * @param orderNo
     * @return
     */
    @Override
    public TrdOrderInfoDto findByOrderNoPurchaser(String orderNo) {
        TrdOrderInfoDto trdOrderInfoDto = (TrdOrderInfoDto) dao.findForObject(getSqlName("findByOrderNoPurchaser"), orderNo);
        return findByOrderNo(trdOrderInfoDto, orderNo);
    }

    /**
     * 运营平台根据订单号获取订单信息
     *
     * @param trdOrderInfoDto
     * @param orderNo
     * @return
     */
    private TrdOrderInfoDto findByOrderNo(TrdOrderInfoDto trdOrderInfoDto, String orderNo) {
        if (null != trdOrderInfoDto) {
            trdOrderInfoDto.setOrderStatusCode(trdOrderInfoDto.getOrderStatus().getCode());
            trdOrderInfoDto.setOrderStatusName(trdOrderInfoDto.getOrderStatus().getName());
            trdOrderInfoDto.setOrderTypeName(trdOrderInfoDto.getOrderType().getName());
            List<TrdOrderGoodsRelDto> trdOrderGoodsRels = trdOrderGoodsRelService.findByOrderNo(orderNo, 1);
            trdOrderInfoDto.setOrderGoods(trdOrderGoodsRels);
            //获取最后添加商品的商品类别
            if (null != trdOrderGoodsRels && trdOrderGoodsRels.size() > 0) {
                TrdOrderGoodsRelDto lastOne = trdOrderGoodsRels.get(trdOrderGoodsRels.size() - 1);
                if (null != lastOne && null != lastOne.getGoodsTypeId()) {
                    GoodsType goodsType = goodsTypeService.findById(lastOne.getGoodsTypeId());
                    if (null != goodsType) {
                        trdOrderInfoDto.setGoodsTypeId(goodsType.getId());
                        trdOrderInfoDto.setGoodsTypeName(goodsType.getName());
                    }
                }
            }
            List<TrdOrderFileRel> trdOrderFileRels= trdOrderFileRelService.findByOrderNo(orderNo);
            List<TrdOrderFileRelDto> TrdOrderFileRelDtos=new  ArrayList<TrdOrderFileRelDto>();
            if(trdOrderFileRels!=null && trdOrderFileRels.size()>0){
                for(TrdOrderFileRel trdOrderFileRel:trdOrderFileRels){
                    TrdOrderFileRelDto trdOrderFileRelDto=new TrdOrderFileRelDto();
                    EntityUtils.copyPropertiesIgnoreNull(trdOrderFileRel, trdOrderFileRelDto);
                    if(trdOrderFileRel.getFileId()!=null){
                        SysFile file= sysFileService.getFileInfo(trdOrderFileRel.getFileId());
                        trdOrderFileRelDto.setFileUrl(file.getFileLocation());
                    }
                    TrdOrderFileRelDtos.add(trdOrderFileRelDto);
                }
            }
            trdOrderInfoDto.setTrdOrderFileRelsDto(TrdOrderFileRelDtos);
        }
        //订单确认单
        PathPDFDto filePathConfirm = trdOrderConfirmationService.findPathByOrderNo(orderNo);
        if(null != filePathConfirm){
            trdOrderInfoDto.setOrderConfirmUrl(filePathConfirm.getPath());
        }
        //订单收货单
        PathPDFDto filePathDelivery = trdOrderDeliveryService.findPathByOrderNo(orderNo);
        if(null != filePathDelivery){
            trdOrderInfoDto.setOrderDeliverUrl(filePathDelivery.getPath());
        }
        return trdOrderInfoDto;
    }

    /**
     * 根据文件id获取
     *
     * @param fileId
     * @return
     */
    private String getOrderFilePath(String fileId) {
        if (!StringUtils.isEmpty(fileId)) {
            SysFile sysFile = sysFileService.getFileInfo(fileId);
            if (sysFile != null) {
                return sysFile.getFileLocation();
            }
        }
        return null;
    }

    /**
     * 根据订单号删除
     *
     * @param orderNos
     * @param orderChannel 1:客户下单； 2： 平台代下单
     */
    @Override
    public void batchDeleteByOrderNos(List<String> orderNos, Integer orderChannel) {
        if (null == orderNos || orderNos.size() <= 0) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_ILLEGAL);
        }
        for (String orderNo : orderNos) {
            validateOrderStatus(orderNo, null, TrdErrorCodes.ERROR_ORDER_DRAFT_CAN_DELETE, orderChannel, true);
        }
        ParamData paramData = new ParamData();
        paramData.put("orderNos", orderNos);
        dao.delete(getSqlName("batchDeleteByOrderNos"), paramData);
    }

    /**
     * 修改订单信息
     * @param trdOrder
     */
    @Override
    public void update(TrdOrder trdOrder){
        dao.update(getSqlName("updateSelective"), trdOrder);
    }

    /**
     * 修改订单信息
     * @param trdOrder
     */
    @Override
    public void updateOrder(TrdOrder trdOrder) {
        //判断订单是否为待收货状态
        TrdOrder orderInfo = findByOrderNo(trdOrder.getOrderNo());
        if (null != orderInfo && !orderInfo.getOrderStatus().getCode().equals(TrdOrderStatus.TRANSPORT.getCode())) {
            throw Exceptions.bizException(TrdErrorCodes.ERROR_ORDER_STATUS_CANNOT_JUMP, TrdOrderStatus.TRANSPORT.getName());
        }
        //计算汇率转换
        trdOrder.setCurrencyCode(populateOrderCurrencyCode(trdOrder.getOrderGoods(), DEFAULT_CURRENCY_CODE));
        trdOrder = exchangeRate(trdOrder);
        try {
            dao.update(getSqlName("updateSelective"), trdOrder);
        } catch (DataIntegrityViolationException e) {
            throw Exceptions.bizException(TrdErrorCodes.ERROR_ORDER_AMOUNT_TOO_LARGE);
        }
        //添加订单操作记录
        TrdOrder order = findByOrderNo(trdOrder.getOrderNo());
        trdOrderTrackingService.save(trdOrder.getOrderNo(), order.getOrderStatus().getCode(), trdOrder.getOrderStatus().getCode(), "修改订单状态", PrincipalUtils.getAccountId());
    }

    /**
     * 批量修改
     *
     * @param orderNos
     * @param trdOrderStatus
     */
    @Override
    public void batchUpdateOrderStatus(List<String> orderNos, TrdOrderStatus trdOrderStatus) {
        for (String orderNo : orderNos) {
            TrdOrder order = findByOrderNo(orderNo);
            TrdOrderStatus statusFrom = TrdOrderStatus.DRAFT;
            switch (trdOrderStatus) {
                case DELIVERY:
                    statusFrom = TrdOrderStatus.CONFIRMING;
                    break;
                case TRANSPORT:
                    statusFrom = TrdOrderStatus.DELIVERY;
                    break;
                default:
                    break;
            }
            //状态是否跳跃
            isSkipStatus(orderNo, statusFrom, trdOrderStatus, order.getOrderStatus());
        }
        ParamData paramData = new ParamData();
        paramData.put("orderNos", orderNos);
        paramData.put("orderStatus", trdOrderStatus);
        dao.update(getSqlName("batchUpdateOrderStatus"), paramData);
    }

    /**
     * 判断订单状态是否有跳跃情况
     *
     * @param orderNo
     * @param statusFrom
     * @param statusTo
     * @param oldStatus
     */
    private void isSkipStatus(String orderNo, TrdOrderStatus statusFrom, TrdOrderStatus statusTo, TrdOrderStatus oldStatus) {
        if (!oldStatus.getCode().equals(statusFrom.getCode())) {
            throw Exceptions.bizException(TrdErrorCodes.ERROR_ORDER_STATUS_CANNOT_JUMP, statusFrom.getName());
        }
        //添加订单操作记录
        trdOrderTrackingService.save(orderNo, statusFrom.getCode(), statusTo.getCode(), "修改订单状态", PrincipalUtils.getAccountId());
    }

    /**
     * 编辑订单
     *
     * @param trdOrderDto
     * @param orderChannel
     */
    @Override
    public void update(TrdOrderDto trdOrderDto, Integer orderChannel) {
        if (null == trdOrderDto) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_ILLEGAL);
        }
        //已签收的订单不能修改
        validateOrderStatus(trdOrderDto.getOrderNo(), trdOrderDto.getOrderStatus(), TrdErrorCodes.ERROR_ORDER_SIGNED_CAN_NOT_EDIT, orderChannel, false);
        //项目是否结项
        validateProject(trdOrderDto.getProjectId());

        TrdOrder trdOrder = new TrdOrder();
        BeanUtils.copyProperties(trdOrderDto, trdOrder);
        dao.update(getSqlName("updateSelective"), trdOrder);
        //删除订单下原有商品
        trdOrderGoodsRelService.deleteByOrderNo(trdOrder.getOrderNo(), 1);
        //保存订单商品信息
        BigDecimal amountDue = saveOrderGoods(trdOrderDto.getOrderGoods(), trdOrder.getOrderNo(), false, orderChannel, null);
        //回写订单总金额
        updateOrderInfo(trdOrder, amountDue, trdOrderDto.getOrderGoods());
    }

    /**
     * 只有草稿状态的订单可以修改
     *  @param orderNo
     * @param errorCode
     * @param isDelete
     */
    private void validateOrderStatus(String orderNo, TrdOrderStatus statusTo, ErrorCode errorCode, Integer orderChannel, boolean isDelete) {
        TrdOrder order = findByOrderNo(orderNo);
        if (null != order) {
            //平台不能删除客户下的单， 客户不能删除平台待下的单
            validateOrderChannel(order.getOrderChannel(), orderChannel, isDelete);
            if (order.getOrderStatus().getCode().equals(TrdOrderStatus.SIGNED.getCode())) {
                throw Exceptions.bizException(errorCode);
            }
            //添加订单操作记录
            trdOrderTrackingService.save(order.getOrderNo(), order.getOrderStatus().getCode(), null == statusTo ? order.getOrderStatus().getCode() : statusTo.getCode(), "修改删除订单", PrincipalUtils.getAccountId());
        }

    }

    /**
     * 平台不能删除客户下的单， 客户不能删除平台待下的单
     *  @param orderChannel
     * @param orderChannelType
     * @param isDelete
     */
    private void validateOrderChannel(Integer orderChannel, Integer orderChannelType, boolean isDelete) {
        if (orderChannel.compareTo(orderChannelType) != 0) {
            if (orderChannelType.compareTo(1) == 0) {
                throw Exceptions.bizException(TrdErrorCodes.ERROR_ORDER_CUSTOMER_CANNOT_DELETE_PLATFORM_ORDER);
            } else if(isDelete){
                throw Exceptions.bizException(TrdErrorCodes.ERROR_ORDER_PLATFORM_CANNOT_DELETE_CUSTOMER_ORDER);
            }
        }
    }

    /**
     * 客户平台销售订单查询（客户订单查询）
     *
     * @param params
     * @return
     */
    @Override
    public QResultDto findByFilterCustomerSale(QueryParams params) {
        ParamData pd = convertQueryParams(params);
        if (null == pd) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_ILLEGAL);
        }
        //判断帐号是否是主帐号
        pd.put("isSystem", false);
        Integer cusUserId = (Integer) pd.get("cusUserId");
        if (StringUtils.isEmpty(cusUserId)) {
            cusUserId = PrincipalUtils.getAccountId();
            pd.put("cusUserId", cusUserId);
            CusUser primaryAccount = isPrimaryAccount(cusUserId);
            if (null != primaryAccount && primaryAccount.getIsSystem()) {
                pd.put("isSystem", true);
                pd.put("primaryAccount", primaryAccount.getRefCustomerId());
            }
        }
        //根据条件获取列表
        List<TrdOrderListCustomerDto> trdOrderListDtos = dao.findForList(getSqlName("findByFilterListPageCustomerSale"), pd, TrdOrderListCustomerDto.class);

        return findByFilterCustomer(trdOrderListDtos, pd);
    }

    /**
     * 是否主帐号
     *
     * @param customerId
     * @return
     */
    private CusUser isPrimaryAccount(Integer customerId) {
        return customerUserService.findById(customerId);
    }

    /**
     * 客户平台采购订单查询（供应商订单查询）
     *
     * @param params
     * @return
     */
    @Override
    public QResultDto findByFilterCustomerPurchaser(QueryParams params) {
        if (null == params) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_ILLEGAL);
        }
        //换取供应商信息
        SupplierDto supplierDto = supplierService.findCurrTrdSupplier();
        if(null == supplierDto){
            throw Exceptions.bizException(TrdErrorCodes.ERROR_ORDER_SUPPLIER_NOT_EXIST);
        }
        params.put("cusUserId", supplierDto.getId());
        ParamData pd = convertQueryParams(params);
        //根据条件获取账单列表
        List<TrdOrderListCustomerDto> trdOrderListDtos = dao.findForList(getSqlName("findByFilterListPageCustomerPurchaser"), pd, TrdOrderListCustomerDto.class);

        return findByFilterCustomer(trdOrderListDtos, pd);
    }

    /**
     * 客户系统订单列表
     *
     * @param trdOrderListDtos
     * @return
     */
    private QResultDto findByFilterCustomer(List<TrdOrderListCustomerDto> trdOrderListDtos, ParamData pd) {
        if (null != trdOrderListDtos && trdOrderListDtos.size() > 0) {
            for (TrdOrderListCustomerDto trdOrderListDto : trdOrderListDtos) {
                //商品类别数组
                List<TrdOrderGoodsTypeShortDto> goodsTypes = trdOrderGoodsRelService.findGoodsTypeShortByOrderNo(trdOrderListDto.getOrderNo(), null);
                trdOrderListDto.setGoodsTypes(goodsTypes);
                //商品列表
                List<TrdOrderGoodsRelShortDto> orderGoods = trdOrderGoodsRelService.findShortByOrderNo(trdOrderListDto.getOrderNo(), null);
                trdOrderListDto.setOrderGoods(orderGoods);
                //订单确认单
                PathPDFDto filePathConfirm = trdOrderConfirmationService.findPathByOrderNo(trdOrderListDto.getOrderNo());
                if (null != filePathConfirm) {
                    trdOrderListDto.setOrderConfirmUrl(filePathConfirm.getPath());
                }
                //订单收货单
                PathPDFDto filePathDelivery = trdOrderDeliveryService.findPathByOrderNo(trdOrderListDto.getOrderNo());
                if (null != filePathDelivery) {
                    trdOrderListDto.setOrderDeliverUrl(filePathDelivery.getPath());
                }
            }
        }
        return new QResultDto(trdOrderListDtos, pd.getPagination());
    }

    /**
     * 订单列表
     *
     * @param params
     * @return
     */
    @Override
    public QResultDto findByFilterSale(QueryParams params) {
        ParamData pd = convertQueryParams(params);
        //判断用户是否有查看对应订单的权限
        pd.putAll(projectService.userProjectPermission());
        //根据条件获取账单列表
        List<TrdOrderListDto> trdOrderListDtos = dao.findForList(getSqlName("findByFilterListPageSale"), pd, TrdOrderListDto.class);
        return findByFilter(trdOrderListDtos, pd);
    }


    /**
     * 采购订单列表
     *
     * @param params
     * @return
     */
    @Override
    public QResultDto findByFilterPurchaser(QueryParams params) {
        ParamData pd = convertQueryParams(params);
        //判断用户是否有查看对应订单的权限
        pd.putAll(projectService.userProjectPermission());
        //根据条件获取账单列表
        List<TrdOrderListDto> trdOrderListDtos = dao.findForList(getSqlName("findByFilterListPagePurchaser"), pd, TrdOrderListDto.class);

        return findByFilter(trdOrderListDtos, pd);
    }

    /**
     * 订单列表
     *
     * @param trdOrderListDtos
     * @return
     */
    private QResultDto findByFilter(List<TrdOrderListDto> trdOrderListDtos, ParamData pd) {
        if (null != trdOrderListDtos && trdOrderListDtos.size() > 0) {
            for (TrdOrderListDto trdOrderListDto : trdOrderListDtos) {
                trdOrderListDto.setOrderStatusCode(trdOrderListDto.getOrderStatus().getCode());
                trdOrderListDto.setOrderStatusName(trdOrderListDto.getOrderStatus().getName());
                trdOrderListDto.setOrderTypeName(trdOrderListDto.getOrderType().getName());
                List<TrdOrderGoodsRelShortDto> trdOrderGoodsRelShortDtos = trdOrderGoodsRelService.findShortByOrderNo(trdOrderListDto.getOrderNo(), null);
                trdOrderListDto.setOrderGoods(trdOrderGoodsRelShortDtos);
                //订单确认单
                PathPDFDto filePathConfirm = trdOrderConfirmationService.findPathByOrderNo(trdOrderListDto.getOrderNo());
                if (null != filePathConfirm) {
                    trdOrderListDto.setOrderConfirmUrl(filePathConfirm.getPath());
                }
                //订单收货单
                PathPDFDto filePathDelivery = trdOrderDeliveryService.findPathByOrderNo(trdOrderListDto.getOrderNo());
                if (null != filePathDelivery) {
                    trdOrderListDto.setOrderDeliverUrl(filePathDelivery.getPath());
                }
            }
        }
        return new QResultDto(trdOrderListDtos, pd.getPagination());
    }

    /**
     * 下单
     *
     * @param trdOrderDto
     * @throws ParseException
     */
    @Override
    public String save(TrdOrderDto trdOrderDto) throws ParseException {
        if (null == trdOrderDto) {
            throw Exceptions.bizException(ErrorCodes.ERROR_ARGUMENT_ILLEGAL);
        }
        //项目是否结项
        validateProject(trdOrderDto.getProjectId());
        //销售订单验证采购方是否锁定
//        validatePurchaser(trdOrderDto);
        //复制属性
        TrdOrder trdOrder = new TrdOrder();
        BeanUtils.copyProperties(trdOrderDto, trdOrder);
    
        String orderNo =
                null;
        try {
            orderNo = OrderMake.generateOrderWaybillNo(OrdServiceTypeEnum.Trading);
        } catch (Exception e) {
            e.printStackTrace();
        }
        trdOrder.setOrderNo(orderNo);
        trdOrder.setCreateUserId(PrincipalUtils.getAccountId());
        super.save(trdOrder);
        //保存订单商品信息
        BigDecimal amountDue = saveOrderGoods(trdOrderDto.getOrderGoods(), trdOrder.getOrderNo(), false, trdOrderDto.getOrderChannel(), null);
        //回写订单总金额
        updateOrderInfo(trdOrder, amountDue, trdOrderDto.getOrderGoods());
        //添加订单操作记录
        String statusTo = TrdOrderStatus.DRAFT.getCode();
        if (null != trdOrder && null != trdOrder.getOrderStatus()) {
            statusTo = trdOrder.getOrderStatus().getCode();
        }
        List<TrdOrderFileRel>  trdOrderFileRels=trdOrderDto.getTrdOrderFileRels();
        if(trdOrderFileRels!=null && trdOrderFileRels.size()>0){
            trdOrderFileRelService.saveOrdFiles(orderNo,statusTo,trdOrderFileRels);
        }
        trdOrderTrackingService.save(orderNo, TrdOrderStatus.DRAFT.getCode(), statusTo, "添加订单", PrincipalUtils.getAccountId());
        return orderNo;
    }

    /**
     * 客户平台下单
     *
     * @param trdOrderDto
     * @return
     */
    @Override
    public String saveForCustomer(TrdOrderDto trdOrderDto) throws ParseException {
        CusUser cusUser = customerUserService.findById(trdOrderDto.getPurchaserId());
        if (ObjectUtils.isEmpty(cusUser)) {
            throw Exceptions.bizException(TrdErrorCodes.ERROR_ORDER_PURCHASER_NOT_EXIST);
        }
        List<Project> projects = projectService.findSimpleProjects(TrdOrderType.SALE.name(), trdOrderDto.getSellerId(), cusUser.getRefCustomerId());
        if (null != projects && projects.size() > 0) {
            trdOrderDto.setProjectId(projects.get(0).getId());
            trdOrderDto.setProjectCode(projects.get(0).getCode());
        } else {
            throw Exceptions.bizException(TrdErrorCodes.ERROR_ORDER_PROJECT_NOT_EXIST);
        }
        return save(trdOrderDto);
    }

    /**
     * 售订单验证采购方是否锁定
     *
     * @param trdOrderDto
     */
    private void validatePurchaser(TrdOrderDto trdOrderDto) {
        if (null != trdOrderDto && null != trdOrderDto.getPurchaserId()) {
            if (null != trdOrderDto.getOrderType() && trdOrderDto.getOrderType().getCode().equals(TrdOrderType.SALE.getCode())) {
                CusUser cusUser = customerUserService.findById(trdOrderDto.getPurchaserId());
                if (ObjectUtils.isEmpty(cusUser)) {
                    throw Exceptions.bizException(TrdErrorCodes.ERROR_ORDER_PURCHASER_NOT_EXIST);
                }
                if (cusUser.getIsLocked()) {
                    throw Exceptions.bizException(TrdErrorCodes.ERROR_ORDER_PURCHASER_IS_LOCKED);
                }
                //客户信息
                CusCustomerDto customerInfo = customerService.findById(cusUser.getRefCustomerId());
                if (null != customerInfo && customerInfo.getLocked()) {
                    throw Exceptions.bizException(TrdErrorCodes.ERROR_ORDER_PURCHASER_IS_LOCKED);
                }
            }
        }
    }

    /**
     * 验证订单项目
     *
     * @param projectId
     */
    private void validateProject(Integer projectId) {
        if (null != projectId) {
            Project projectInfo = projectService.findBaseById(projectId);
            if (null == projectInfo || projectInfo.getIsDeleted()) {
                throw Exceptions.bizException(TrdErrorCodes.ERROR_ORDER_PROJECT_NOT_EXIST);
            } else if (projectInfo.getStatus() != ProjectConstants.Status.APPROVED) {
                throw Exceptions.bizException(TrdErrorCodes.ERROR_ORDER_PROJECT_STATUS_ERROR);
            }
        }
    }

    /**
     * 验证所选商品
     *
     * @param orderGoods
     */
    private void isSameCurrency(List<TrdOrderGoodsSaveDto> orderGoods) {
        if (null != orderGoods && orderGoods.size() > 0) {
            TrdOrderGoodsSaveDto orderGoodsTemp = orderGoods.get(0);
            GoodsInfoDto goodsInfoTemp = goodsService.findById(orderGoodsTemp.getGoodsId());
            for (TrdOrderGoodsSaveDto trdOrderGoodsSaveDto : orderGoods) {
                GoodsInfoDto goodsInfo = goodsService.findById(trdOrderGoodsSaveDto.getGoodsId());
                //商品是否存在
                if (null == goodsInfo || goodsInfo.getDeleted()) {
                    throw Exceptions.bizException(TrdErrorCodes.ERROR_ORDER_GOODS_NOT_EXIST);
                }
                //所选商品货币不统一
                if (null != goodsInfoTemp && !goodsInfoTemp.getCurrencyType().equals(goodsInfo.getCurrencyType())) {
                    throw Exceptions.bizException(TrdErrorCodes.ERROR_ORDER_GOODS_CURRENCY_DISUNITY);
                }
            }
        } else {
            throw Exceptions.bizException(TrdErrorCodes.ERROR_ORDER_GOODS_EMPTY);
        }
    }

    /**
     * 回写订单信息
     *
     * @param trdOrder
     * @param amountDue
     * @param orderGoods
     */
    private void updateOrderInfo(TrdOrder trdOrder, BigDecimal amountDue, List<TrdOrderGoodsSaveDto> orderGoods) {
        //组装更新数据
        TrdOrder trdOrderUpdate = new TrdOrder();
        trdOrderUpdate.setOrderNo(trdOrder.getOrderNo());
        trdOrderUpdate.setAmountDue(amountDue);
        trdOrderUpdate.setIsDeleted(trdOrder.getIsDeleted());
        trdOrderUpdate.setBusinessType(trdOrder.getBusinessType());
        trdOrderUpdate.setLastUpdateUserId(PrincipalUtils.getAccountId());
        trdOrderUpdate.setCurrencyCode(populateOrderCurrencyCode(orderGoods, DEFAULT_CURRENCY_CODE));
        //默认币种CNY
        trdOrderUpdate.setCustCurrencyCode(DEFAULT_CURRENCY_CODE);
        //帐号信息
        if (trdOrder.getOrderType().getCode().equals(TrdOrderType.SALE.getCode())) {
            trdOrderUpdate.setCusUserId(trdOrder.getPurchaserId());
            CusUser cusUser = customerUserService.findById(trdOrderUpdate.getCusUserId());
            if (ObjectUtils.isEmpty(cusUser)) {
                throw Exceptions.bizException(TrdErrorCodes.ERROR_ORDER_PURCHASER_NOT_EXIST);
            }
            trdOrderUpdate.setCustomerId(cusUser.getRefCustomerId());
            //客户信息
            CusCustomerDto customerInfo = customerService.findById(cusUser.getRefCustomerId());
            if (null != customerInfo && !StringUtils.isEmpty(customerInfo.getTradingCurrency())) {
                //客户设置的币种
                trdOrderUpdate.setCustCurrencyCode(customerInfo.getTradingCurrency());
            }
        }
        //计算汇率转换
        trdOrderUpdate = exchangeRate(trdOrderUpdate);
        try {
            dao.update(getSqlName("updateSelective"), trdOrderUpdate);
        } catch (DataIntegrityViolationException e) {
            throw Exceptions.bizException(TrdErrorCodes.ERROR_ORDER_AMOUNT_TOO_LARGE);
        }
    }

    /**
     * 转换客户币种汇率
     *
     * @param trdOrderUpdate
     * @return
     */
    private TrdOrder exchangeRate(TrdOrder trdOrderUpdate) {
        BigDecimal amountDue = trdOrderUpdate.getAmountDue();
        if(null == amountDue || amountDue.compareTo(BigDecimal.ZERO) < 0){
            return trdOrderUpdate;
        }
        Date now = dao.getDbDate();
        //计算汇率转换
        if (null != trdOrderUpdate && StringUtils.isEmpty(trdOrderUpdate.getCustCurrencyCode())) {
            TrdOrder trdOrderNow = findByOrderNo(trdOrderUpdate.getOrderNo());
            if (null != trdOrderNow && !StringUtils.isEmpty(trdOrderNow.getCustCurrencyCode())) {
                trdOrderUpdate.setCustCurrencyCode(trdOrderNow.getCustCurrencyCode());
                now = trdOrderNow.getOrderTime();
            } else {
                trdOrderUpdate.setCustCurrencyCode(DEFAULT_CURRENCY_CODE);
            }
        }
        if (null != trdOrderUpdate && StringUtils.isEmpty(trdOrderUpdate.getCurrencyCode())) {
            trdOrderUpdate.setCurrencyCode(DEFAULT_CURRENCY_CODE);
        }
        if (trdOrderUpdate.getCurrencyCode().equals(trdOrderUpdate.getCustCurrencyCode())) {
            trdOrderUpdate.setCustCurrencyAmount(trdOrderUpdate.getAmountDue());
            trdOrderUpdate.setExchangeRate(BigDecimal.ONE);
        } else {
            //转换汇率
            ExchangeRate exchangeRate = exchangeRateService.findCurrencyRoeByDate(trdOrderUpdate.getCurrencyCode(), trdOrderUpdate.getCustCurrencyCode(), now);
            if (exchangeRate != null) {
                trdOrderUpdate.setCustCurrencyAmount(trdOrderUpdate.getAmountDue().multiply(exchangeRate.getRate()));
                trdOrderUpdate.setExchangeRate(exchangeRate.getRate());
            } else {
                throw Exceptions.bizException(TrdErrorCodes.ERROR_ORDER_EXCHANGE_ERROR);
            }
        }
        if(null != trdOrderUpdate){
            if(null != trdOrderUpdate.getCustCurrencyAmount()){
                BigDecimal custAmount = trdOrderUpdate.getCustCurrencyAmount();
                trdOrderUpdate.setCustCurrencyAmount(custAmount.setScale(3, BigDecimal.ROUND_HALF_UP));
            }
            if(null != trdOrderUpdate.getCustCurrencyAmountReceived()){
                BigDecimal custAmountReceived = trdOrderUpdate.getCustCurrencyAmountReceived();
                trdOrderUpdate.setCustCurrencyAmountReceived(custAmountReceived.setScale(3, BigDecimal.ROUND_HALF_UP));
            }
        }
        return trdOrderUpdate;
    }

    /**
     * 根据商品货币类型回写订单货币类型
     *
     * @param orderGoods
     * @return
     */
    private String populateOrderCurrencyCode(List<TrdOrderGoodsSaveDto> orderGoods, String currencyCode) {
        if (null != orderGoods && orderGoods.size() > 0) {
            TrdOrderGoodsSaveDto trdOrderGoodsSaveDto = orderGoods.get(0);
            GoodsInfoDto goodsInfo = goodsService.findById(trdOrderGoodsSaveDto.getGoodsId());
            if (null != goodsInfo) {
                currencyCode = goodsInfo.getCurrencyType();
            }
        }
        return currencyCode;
    }

    /**
     * 保存订单商品信息
     *
     * @param orderGoods
     * @param orderNo
     * @param isCalculateAmount
     * @param orderChannel  1： 客户系统下单； 2： 运营系统下单
     * @param vat
     * @return
     */
    @Override
    public BigDecimal saveOrderGoods(List<TrdOrderGoodsSaveDto> orderGoods, String orderNo, boolean isCalculateAmount, Integer orderChannel, BigDecimal vat) {
        //验证所选商品
        isSameCurrency(orderGoods);
        BigDecimal orderAmountDue = BigDecimal.ZERO;
        if (null != orderGoods && orderGoods.size() > 0) {
            for (TrdOrderGoodsSaveDto trdOrderGoodsRelDto : orderGoods) {
                GoodsInfoDto goodsInfo = goodsService.findById(trdOrderGoodsRelDto.getGoodsId());
                TrdOrderGoodsRel trdOrderGoodsRel = new TrdOrderGoodsRel();
                trdOrderGoodsRel.setOrderNo(orderNo);
                trdOrderGoodsRel.setGoodsId(trdOrderGoodsRelDto.getGoodsId());
                trdOrderGoodsRel.setGoodsPrice(trdOrderGoodsRelDto.getGoodsPrice());
                trdOrderGoodsRel.setMinLimit(trdOrderGoodsRelDto.getMinLimit());
                trdOrderGoodsRel.setMaxLimit(trdOrderGoodsRelDto.getMaxLimit());
                if (null != goodsInfo) {
                    trdOrderGoodsRel.setGoodsName(goodsInfo.getName());
                    trdOrderGoodsRel.setGoodsHSCode(goodsInfo.getHsCode());
                    if(null == trdOrderGoodsRel.getGoodsPrice()){
                        trdOrderGoodsRel.setGoodsPrice(goodsInfo.getPrice());
                    }
                    trdOrderGoodsRel.setGoodsCurrencyType(goodsInfo.getCurrencyType());
                    trdOrderGoodsRel.setGoodsTypeId(goodsInfo.getGoodsTypeId());
                    trdOrderGoodsRel.setGoodsUnit(goodsInfo.getUnit());
                    trdOrderGoodsRel.setGoodsCode(goodsInfo.getCode());
                } else {
                    throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "根据商品id不能找到对应的商品");
                }
                //收货确认单或者客户系统下单，计算订单金额
                if(isCalculateAmount){  //收货确认单填写的具体数量，计算总金额
                    BigDecimal goodsNum = trdOrderGoodsRelDto.getGoodsNum();
                    if(null != goodsNum){
                        trdOrderGoodsRel.setGoodsNum(goodsNum);
                        //计算总金额
                        BigDecimal amount = trdOrderGoodsRel.getGoodsPrice().multiply(trdOrderGoodsRelDto.getGoodsNum());
                        amount = amount.setScale(2, BigDecimal.ROUND_HALF_UP);
                        orderAmountDue = orderAmountDue.add(amount);
                        trdOrderGoodsRel.setAmountDue(amount);
                    }
                }else{  //下单商品数量范围为1个的时候需要将数量回写
                    BigDecimal minLimit = trdOrderGoodsRelDto.getMinLimit();
                    BigDecimal maxLimit = trdOrderGoodsRelDto.getMaxLimit();
                    if(null == minLimit && null != maxLimit){
                        trdOrderGoodsRel.setGoodsNum(maxLimit);
                    }else if(null != minLimit && null == maxLimit){
                        trdOrderGoodsRel.setGoodsNum(minLimit);
                    }else if(null != minLimit && null != maxLimit){
                        if(minLimit.compareTo(maxLimit) == 0){
                            trdOrderGoodsRel.setGoodsNum(minLimit);
                        }
                    }
                }
                trdOrderGoodsRelService.save(trdOrderGoodsRel);
            }
        }
        //金额 = 收货确认单商品总金额 + 增值税
        if(isCalculateAmount && null != vat){
            orderAmountDue = orderAmountDue.add(vat);
        }
        return orderAmountDue.setScale(2, BigDecimal.ROUND_HALF_UP);
    }


    /**
     * 账单管理添加接口
     * 获取需要生成的账单的信息
     *
     * @param type            1销售账单 2采购账单
     * @param bizCompanyIds   bizCompanyIds
     * @param platformIds     platformIds
     * @param startEffectTime startEffectTime
     * @param endEffectTime   endEffectTime
     */
    @Override
    public Integer countGenerateBillings(int type, List<Integer> bizCompanyIds, List<Integer> platformIds, Date startEffectTime, Date endEffectTime) {
        ParamData paramData = new ParamData();
        paramData.put("bizCompanyIds", bizCompanyIds);
        paramData.put("platformIds", platformIds);
        paramData.put("type", type);
        paramData.put("startEffectTime", startEffectTime);
        paramData.put("endEffectTime", endEffectTime);

        return (Integer) dao.findForObject(getSqlName("countGenerateBillings"), paramData);
    }


    /**
     * 获取订单
     *
     * @param type            type
     * @param bizCompanyIds   bizCompanyIds
     * @param platformIds     platformIds
     * @param startEffectTime startEffectTime
     * @param endEffectTime   endEffectTime
     * @param isBilled        isBilled
     * @return List
     */
    @Override
    public List<TrdBillingGenerateDto> getOrderByCreatBillQuery(int type,
                                                                List<Integer> bizCompanyIds, List<Integer> platformIds,
                                                                Date startEffectTime, Date endEffectTime,
                                                                boolean isBilled) {
        ParamData paramData = new ParamData();
        paramData.put("bizCompanyIds", bizCompanyIds);
        paramData.put("platformIds", platformIds);
        paramData.put("startEffectTime", startEffectTime);
        paramData.put("endEffectTime", endEffectTime);
        paramData.put("isBilled", isBilled);
        paramData.put("type", type);

        return dao.findForList(getSqlName("getOrderByCreatBillQuery"), paramData, TrdBillingGenerateDto.class);
    }

    @Override
    public SysFile getPDFConfirmationByOrder(TrdOrderConfirmationInfoDto trdOrderConfirmationInfoDto) {
        if (trdOrderConfirmationInfoDto != null) {
            Map<String, Object> dataMap = new HashMap<>();
            SimpleDateFormat ft = new SimpleDateFormat("dd-MMMM-yyyy", Locale.US);
            dataMap.put("custCompanyName", trdOrderConfirmationInfoDto.getCustCompanyName());
            dataMap.put("custCompanyNickName", trdOrderConfirmationInfoDto.getCustCompanyNickName());
            dataMap.put("custCompanyAddress", trdOrderConfirmationInfoDto.getCustCompanyAddress());
            dataMap.put("orderNo", trdOrderConfirmationInfoDto.getOrderNo());
            dataMap.put("custOrderNo", trdOrderConfirmationInfoDto.getCustOrderNo());
            dataMap.put("orderTime", trdOrderConfirmationInfoDto.getOrderTime() != null ? ft.format
                    (trdOrderConfirmationInfoDto.getOrderTime()) : "");

            dataMap.put("shipName", trdOrderConfirmationInfoDto.getShipName());
            dataMap.put("imoCode", trdOrderConfirmationInfoDto.getImoCode());
            dataMap.put("destinationPort", trdOrderConfirmationInfoDto.getDestinationPort());
            dataMap.put("mooringSite", trdOrderConfirmationInfoDto.getMooringSite());
            dataMap.put("transportStartTime", trdOrderConfirmationInfoDto.getTransportStartTime() != null ? ft.format
                    (trdOrderConfirmationInfoDto.getTransportStartTime()) : "");
            dataMap.put("transportEndTime", trdOrderConfirmationInfoDto.getTransportEndTime() != null ? ft.format
                    (trdOrderConfirmationInfoDto.getTransportEndTime()) : "");
            dataMap.put("transportDuration", trdOrderConfirmationInfoDto.getTransportDuration());
            dataMap.put("transportDurationUnit", trdOrderConfirmationInfoDto.getTransportDurationUnit());
            dataMap.put("sailStartTime", trdOrderConfirmationInfoDto.getSailStartTime() != null ? ft.format
                    (trdOrderConfirmationInfoDto.getSailStartTime()) : "");
            dataMap.put("sailEndTime", trdOrderConfirmationInfoDto.getSailEndTime() != null ? ft.format
                    (trdOrderConfirmationInfoDto.getSailEndTime()) : "");
            dataMap.put("reachStartTime", trdOrderConfirmationInfoDto.getReachStartTime() != null ? ft.format
                    (trdOrderConfirmationInfoDto.getReachStartTime()) : "");
            dataMap.put("reachEndTime", trdOrderConfirmationInfoDto.getReachEndTime() != null ? ft.format
                    (trdOrderConfirmationInfoDto.getReachEndTime()) : "");
            dataMap.put("paymentClause", trdOrderConfirmationInfoDto.getPaymentClause());
            dataMap.put("purchaser", trdOrderConfirmationInfoDto.getPurchaser());
            dataMap.put("agent", trdOrderConfirmationInfoDto.getAgent());
            dataMap.put("note", trdOrderConfirmationInfoDto.getNote());
            dataMap.put("contractClause", trdOrderConfirmationInfoDto.getContractClause());
            dataMap.put("representativePhone", trdOrderConfirmationInfoDto.getRepresentativePhone());
            dataMap.put("companyAddress", trdOrderConfirmationInfoDto.getCompanyAddress());
            dataMap.put("companyPhone", trdOrderConfirmationInfoDto.getCompanyPhone());
            dataMap.put("companyFax", trdOrderConfirmationInfoDto.getCompanyFax());
            dataMap.put("companyEmail", trdOrderConfirmationInfoDto.getCompanyEmail());
            dataMap.put("companyName", trdOrderConfirmationInfoDto.getCompanyName());
            if (trdOrderConfirmationInfoDto.getOrderGoods() != null && trdOrderConfirmationInfoDto.getOrderGoods()
                    .size() > 0) {
                dataMap.put("goodList", trdOrderConfirmationInfoDto.getOrderGoods());
            }
            String content = FreeMarkerTemplateUtils.freeMarkerRender(dataMap, "orderconfirmation.ftl");
            ByteArrayOutputStream outputStream = null;
            try {
                outputStream = (ByteArrayOutputStream) PDFUtils.getPdfStream(content);
            } catch (IOException e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            } catch (DocumentException e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
            if (outputStream != null) {
                ByteArrayInputStream swapStream = new ByteArrayInputStream(outputStream.toByteArray());
                long size = outputStream.toByteArray().length;
                StorePath storePath = storageClient.uploadFile(swapStream, size,
                        "pdf", null);
                SysFile sysFile = sysFileService.uploadFile(0, null, UUIDGenerator.generateOrderedUUID() +
                        "comfirmationOder", "application/pdf", "comfirmationOderPdf", storePath.getFullPath(), size);
                return sysFile;
            }
            return null;
        }
        return null;
    }

    /**
     * 更新是否生成账单的字段
     *
     * @param orderNos orderNos
     * @param type     1销售账单 2采购账单
     * @param isBilled isBilled
     */
    @Override
    public void updateIsBilledStatus(List<String> orderNos, int type, boolean isBilled) {
        ParamData paramData = new ParamData();
        paramData.put("orderNos", orderNos);
        paramData.put("type", type);
        paramData.put("isBilled", isBilled);

        dao.update(getSqlName("updateIsBilledStatus"), paramData);
    }

    @Override
    public String exportPDF(String image, String type, String orderNo) throws IOException {
        Resource resource = new ClassPathResource(File.separator + "templates");
        String path = resource.getFile().getPath();
        UUID uuid = UUID.randomUUID();
        path = path + File.separator + uuid.toString() + ".png";
        String[] str = image.split(",");
        image = str[1];
        StorePath storePath = new StorePath();
        byte[] bt = null;
        try {
            sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
            bt = decoder.decodeBuffer(image);
            FileOutputStream out = new FileOutputStream(path);
            out.write(bt);
            out.close();
            Document document = new Document(PageSize.A4, 50, 50, 50, 50);

            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            PdfWriter writer = PdfWriter.getInstance(document, outputStream);
            writer.setEncryption(null, "1".getBytes(), PdfWriter.ALLOW_SCREENREADERS | PdfWriter.ALLOW_PRINTING, PdfWriter.STANDARD_ENCRYPTION_40);
            document.open();

            // Add Image
            Image image1 = Image.getInstance(path);
            // 根据域的大小缩放图片
            image1.scaleToFit(image1.getWidth() / 2, image1.getHeight() / 2);

            // Fixed Positioning
            image1.setAbsolutePosition(0, 0);
            // Scale to new height and new width of image
            image1.scaleAbsolute(595, 842);
            // Add to document
            document.add(image1);
            document.close();
            writer.close();
            ByteArrayInputStream in = new ByteArrayInputStream(outputStream.toByteArray());
            long fileSizes = in.available();
            storePath = storageClient.uploadFile(in, fileSizes, "pdf", null);
            SysFile sysFile = sysFileService.uploadFile(0, null, UUIDGenerator.generateOrderedUUID() +
                    "comfirmationOder", "application/pdf", "comfirmationOderPdf", storePath.getFullPath(), fileSizes);

            if (sysFile != null) {
                if ("1".equals(type)) {
                    TrdOrderConfirmation upateFileInfoConfirmation = new TrdOrderConfirmation();
                    upateFileInfoConfirmation.setOrderNo(orderNo);
                    upateFileInfoConfirmation.setFileId(sysFile.getFileId());
                    dao.update("TrdOrderConfirmationMapper.updateFiledIdByOrderNo", upateFileInfoConfirmation);
                } else {
                    Map<String, Object> data = new HashMap<>();
                    data.put("fileId", sysFile.getFileId());
                    data.put("orderNo", orderNo);
                    dao.update("TrdOrderDeliveryMapper.updateFiledIdByOderId", data);
                }

            }
            FileUtil.deleteFile(path);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return storePath.getFullPath();
    }

	private String creatPdf(ByteArrayOutputStream outputStream, String type, String orderNo) {
		long fileSizes = (long) 0;
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		Resource resource = new ClassPathResource(File.separator + "templates");
		// 图片路径
		String imagePath = "";
		try {
			imagePath = resource.getFile().getPath();
			imagePath = imagePath + File.separator + "sunrun.png";
			Image image;
			ByteArrayInputStream in = null;
			try {
				image = Image.getInstance(imagePath);

				in = new ByteArrayInputStream(outputStream.toByteArray());
				fileSizes = in.available();
				// 读取模板文件
				PdfReader reader = new PdfReader(in);
				PdfStamper stamper;
				try {
					stamper = new PdfStamper(reader, out);

					// 获取操作的页面
					PdfContentByte under = stamper.getOverContent(1);
					if ("2".equals(type)) {
						// 根据域的大小缩放图片
						image.scaleToFit(130, 150);
						// 添加图片
						image.setAbsolutePosition(40, 777);
					} else {
						// 根据域的大小缩放图片
						image.scaleToFit(130, 150);
						// 添加图片
						image.setAbsolutePosition(424, 732);
					}
					under.addImage(image);

					stamper.close();
					reader.close();
				} catch (DocumentException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			} catch (BadElementException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (MalformedURLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		ByteArrayInputStream swapStream = new ByteArrayInputStream(out.toByteArray());
		StorePath storePath = storageClient.uploadFile(swapStream, out.toByteArray().length, "pdf", null);
		SysFile sysFile = sysFileService.uploadFile(0, null, UUIDGenerator.generateOrderedUUID() + "comfirmationOder",
				"application/pdf", "comfirmationOderPdf", storePath.getFullPath(), fileSizes);
		try {
			swapStream.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if (sysFile != null) {
            TrdOrderInfoDto orderInfo = findByOrderNoSale(orderNo);
              if ("1".equals(type)) {
                  if (null == orderInfo) {
                      TrdOrderConfirmation trdOrderConfirmation = new TrdOrderConfirmation();
                      trdOrderConfirmation.setFileId(sysFile.getFileId());
                      trdOrderConfirmation.setOrderNo(orderNo);
                      dao.save("TrdOrderConfirmationMapper.insertSelective", trdOrderConfirmation);
                      //保存订单附件（订单确认单和订单收货单）
                      saveOrderFile(orderNo, sysFile.getFileId(), TrdOrderFileRel.FILE_TYPE_CONFIRM, UUIDGenerator.generateOrderedUUID() + "confirmationOrder", "confirmationOrderPdf");
                  } else {
                      TrdOrderConfirmation upateFileInfoConfirmation = new TrdOrderConfirmation();
                      upateFileInfoConfirmation.setOrderNo(orderNo);
                      upateFileInfoConfirmation.setFileId(sysFile.getFileId());
                      dao.update("TrdOrderConfirmationMapper.updateFiledIdByOrderNo", upateFileInfoConfirmation);
                  }
              } else {
                  if (null != orderInfo) {
                      TrdOrderDelivery trdOrderDelivery = new TrdOrderDelivery();
                      trdOrderDelivery.setFileId(sysFile.getFileId());
                      trdOrderDelivery.setOrderNo(orderNo);
                      dao.save("TrdOrderDeliveryMapper.insertSelective", trdOrderDelivery);
                      //保存订单附件（订单确认单和订单收货单）
                      saveOrderFile(orderNo, sysFile.getFileId(), TrdOrderFileRel.FILE_TYPE_DELIVERY, UUIDGenerator.generateOrderedUUID() + "deliveryOrder", "deliveryOrderPdf");
                  } else {
                      Map<String, Object> data = new HashMap<>();
                      data.put("fileId", sysFile.getFileId());
                      data.put("orderNo", orderNo);
                      dao.update("TrdOrderDeliveryMapper.updateFiledIdByOderId", data);
                  }
              }
          }
		return storePath.getFullPath();
	}

	private String getPath(String contentHtml, int count, String type, String orderNo) {
		String path = "";
		contentHtml = contentHtml.replaceAll("&amp;Page&amp;", String.valueOf(count));
		String content = FreeMarkerTemplateUtils.tidyHtml(contentHtml);
		ByteArrayOutputStream outputStream = null;
		try {
			outputStream = (ByteArrayOutputStream) PDFUtils.getPdfStream(content);
			if (outputStream != null) {
				path = creatPdf(outputStream, type, orderNo);
                outputStream.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		} catch (DocumentException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		}

		
		return path;
	}

	@Override
	public PDFDto createPDFFile(String type, String orderNo, String contentHtml) {
        if (orderNo == null) {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "orderNo 不能为空");
        }
        TrdOrder trdOrder = this.findFullInfoByOrderNo(orderNo);
        if (trdOrder == null) {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "orderNo 不存在");
        }
        if (!isNeedBuildPDF(trdOrder)) {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "非SUNRUN订单,不能使用该方法");
        }

		PDFDto pdfDto=new PDFDto();
		String path="";
		PdfReader pdf;
		int count = 0;
		contentHtml = contentHtml.replace("\"", "");
		String str = URLDecoder.decode(contentHtml);
		String content = FreeMarkerTemplateUtils.tidyHtml(str);
		ByteArrayOutputStream outputStream = null;
		try {
			outputStream = (ByteArrayOutputStream) PDFUtils.getPdfStream(content);
		} catch (IOException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		} catch (DocumentException e) {
			e.printStackTrace();
			logger.error(e.getMessage());
		}
		if (outputStream != null) {
			try {
				pdf = new PdfReader(outputStream.toByteArray());
				count = pdf.getNumberOfPages();
				outputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			path=getPath(content, count, type, orderNo);
		}
		pdfDto.setPageSize(count);
		pdfDto.setFileUrl(path);
		return pdfDto;
    }

    @Override
    public boolean isNeedBuildPDF(TrdOrder trdOrder) {
        boolean result = false;
        PlatformCompany platformCompany = null;
        if (trdOrder != null && trdOrder.getOrderType() != null) {
            switch (trdOrder.getOrderType()) {
                case SALE:
                    platformCompany = platformCompanyService.getPlatformCompanyById(trdOrder.getSellerId());
                    break;
                case PURCHASE:
                    platformCompany = platformCompanyService.getPlatformCompanyById(trdOrder.getPurchaserId());
                default:
                    break;
            }
            if (platformCompany != null && SystemConstants.PLAT002.equalsIgnoreCase(platformCompany.getCode()) && SystemConstants.PLAT002_NAME.equalsIgnoreCase(platformCompany.getName().trim())) {
                result = true;
            }
        }
        return result;
    }

    @Override
    public void signed(List<String> orders) {
        if (orders == null && orders.size() == 0) {
            throw Exceptions.bizException(ErrorCodes.ERROR_COMMON, "至少选择一个订单");
        }

        List<TrdOrder> trdOrders = findByOrders(orders);
        for (TrdOrder trdOrder : trdOrders){
            if(isNeedBuildPDF(trdOrder)){
                throw Exceptions.bizException(ErrorCodes.ERROR_COMMON,"SUNRUN订单不支持批量签收，请选择一条数据");
            }
        }
        trdOrders.stream().forEach(o->{
            isSkipStatus(o.getOrderNo(),TrdOrderStatus.TRANSPORT,TrdOrderStatus.SIGNED,o.getOrderStatus());
        });

        List<String> orderNos = trdOrders.stream().map(t->t.getOrderNo()).collect(Collectors.toList());
        ParamData paramData = new ParamData();
        paramData.put("orderNos", orderNos);
        paramData.put("orderStatus", TrdOrderStatus.SIGNED);
        dao.update(getSqlName("batchUpdateOrderStatus"), paramData);


    }

    @Override
    public List<TrdOrder> findByOrders(List<String> orders) {
        if (orders != null && orders.size() > 0) {
            ParamData pd = new ParamData();
            pd.put("orders", orders);
            List<TrdOrder> trdOrders = dao.findForList(getSqlName("findBaseByOrders"), pd, TrdOrder.class);
            return trdOrders;
        }
        return null;
    }

    /**
     * 保存订单附件信息
     *
     * @param orderNo
     * @param fileId
     * @param fileType
     * @param fileName
     * @param fileRemark
     */
    private void saveOrderFile(String orderNo, String fileId, Integer fileType, String fileName, String fileRemark) {
        TrdOrderFileRel trdOrderFileRel = new TrdOrderFileRel();
        trdOrderFileRel.setOrderNo(orderNo);
        trdOrderFileRel.setFileId(fileId);
        trdOrderFileRel.setType(fileType);
        trdOrderFileRel.setName(fileName);
        trdOrderFileRel.setRemark(fileRemark);
        trdOrderFileRel.setCreateUserId(PrincipalUtils.getAccountId());
        trdOrderFileRel.setLastUpdateUserId(PrincipalUtils.getAccountId());
        trdOrderFileRelService.save(trdOrderFileRel);
    }

    /**
     * 修改订单附件信息
     * @param orderNo
     * @param fileId
     * @param fileType
     * @param fileName
     * @param fileRemark
     */
    private void updateOrderFile(String orderNo, String fileId, Integer fileType, String fileName, String fileRemark) {
        TrdOrderFileRel trdOrderFileRel = new TrdOrderFileRel();
        trdOrderFileRel.setOrderNo(orderNo);
        trdOrderFileRel.setFileId(fileId);
        trdOrderFileRel.setType(fileType);
        trdOrderFileRel.setName(fileName);
        trdOrderFileRel.setRemark(fileRemark);
        trdOrderFileRel.setLastUpdateUserId(PrincipalUtils.getAccountId());
        trdOrderFileRelService.update(trdOrderFileRel);
    }

    @Override
    public TrdOrder findFullInfoByOrderNo(String orderNo) {
        return (TrdOrder) dao.findForObject(getSqlName("findBaseByOrder"), orderNo);
    }

    @Override
    public List<TrdOrder> findPurByReceiptTimeForRpt(Date dateBegin, Date dateEnd) {
        Map<String, Object> map = new HashMap<>(16);
        map.put("dateBegin", dateBegin);
        map.put("dateEnd", dateEnd);
        map.put("orderType", TrdOrderType.PURCHASE.getCode());
        return dao.findForList(getSqlName("findByReceiptTimeForRpt"),map, TrdOrder.class);
    }
    @Override
    public List<TrdOrder> findSaleByReceiptTimeForRpt(Date dateBegin, Date dateEnd) {
        Map<String, Object> map = new HashMap<>(16);
        map.put("dateBegin", dateBegin);
        map.put("dateEnd", dateEnd);
        map.put("orderType", TrdOrderType.SALE.getCode());
        return dao.findForList(getSqlName("findByReceiptTimeForRpt"),map, TrdOrder.class);
    }

    @Override
    public List<TrdOrderDetail> getOrders() {
        Jedis jedis = RedisPoolManager.getJedis();
        byte[] cacheList = jedis.hget("trdOrderDetails".getBytes(),"log".getBytes());
        if(cacheList!=null && cacheList.length>0){
            jedis.close();
            return (List) SerializeUtil.unserialize(cacheList);
        }
        else{
            ParamData pd = new ParamData();
            List<TrdOrderDetail> trdOrderDetails = dao.findForList(getSqlName("findOrders"), pd, TrdOrderDetail.class);
            jedis.del("trdOrderDetails");
            //增加页面跳转之间的非法判断字段，存入redis中，超时则自动删除
            jedis.hset("trdOrderDetails".getBytes(),"log".getBytes(), SerializeUtil.serialize(trdOrderDetails));
            jedis.expire("trdOrderDetails" , OrderConstants.ORDER_CACHE_TIMEOUT);
            jedis.close();
            return trdOrderDetails;
        }

    }
}
